package com.yycx.module.product.provider.service.impl;

import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.yycx.common.constants.CommonConstants;
import com.yycx.common.enums.VisiableEnum;
import com.yycx.common.mybatis.base.service.impl.BaseServiceImpl;
import com.yycx.common.base.entity.EntityMap;
import com.yycx.common.mybatis.model.ResultBody;
import com.yycx.common.mybatis.query.CriteriaQuery;
import com.yycx.common.mybatis.query.CriteriaSave;
import com.yycx.common.security.OpenHelper;
import com.yycx.common.utils.ApiAssert;
import com.yycx.common.base.utils.FlymeUtils;
import com.yycx.module.product.client.entity.ProdCategory;
import com.yycx.module.product.client.entity.ProdProduct;
import com.yycx.module.product.provider.mapper.ProdCategoryMapper;
import com.yycx.module.product.provider.service.ProdCategoryService;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;

/**
 * 店铺产品分类 实现类
 *
 * @author flyme
 * @date 2019-06-19
 */
@Service
@Transactional(rollbackFor = Exception.class)
public class ProdCategoryServiceImpl extends BaseServiceImpl<ProdCategoryMapper, ProdCategory> implements ProdCategoryService {




    @Override
    public ResultBody beforeListEntityMap(CriteriaQuery<ProdCategory> cq, ProdCategory prodCategory, EntityMap requestMap) {
        EntityMap params = cq.getRequestMap();
        Long categoryId = params.getLong("categoryId");
        String categoryName = params.get("categoryName");
        ApiAssert.isNotEmpty("请选择一级分类", categoryId);
        cq.select(ProdCategory.class, "categoryId", "parentId", "categoryName", "categoryIcon");
        cq.eq("parentId", categoryId);
        cq.likeRight("categoryName", categoryName);
        cq.eq("categoryLevel", CommonConstants.LEVEL_2);
        cq.orderByAsc("sortOrder");
        return super.beforeListEntityMap(cq, prodCategory, requestMap);
    }

    @Override
    @Transactional(propagation = Propagation.SUPPORTS, readOnly = true)
    public ResultBody listAll(Map map) {
        EntityMap config = redisUtils.getConfigMap("GLOBAL_CONFIG");
        Integer maxCategoryLevel = config.get("maxCategoryLevel");
        CriteriaQuery<EntityMap> cq = new CriteriaQuery(map, ProdCategory.class);
        EntityMap params = cq.getRequestMap();
        String categoryName = params.get("categoryName");
        cq.select(ProdCategory.class, "categoryId", "parentId", "categoryName", "categoryIcon", "catagoryState", "sortOrder", "categoryLevel");
        cq.likeRight("categoryName", categoryName);
        cq.orderByAsc("sortOrder");
        ResultBody resultBody = baseList(cq);
        resultBody.put("categoryLevel", maxCategoryLevel);
        return resultBody;
    }


    @Override
    public ResultBody beforeAdd(CriteriaSave cs, ProdCategory category, EntityMap extra) {
        Long companyId = OpenHelper.getCompanyId();
        String categoryName = category.getCategoryName();
        ApiAssert.isNotEmpty("分类名称不能为空", categoryName);
        ProdCategory prodCategory = getProdCategory(categoryName, companyId);
        ApiAssert.isEmpty("分类已存在", prodCategory);

        Long parentId = FlymeUtils.isEmpty(category.getParentId()) ? 0L : category.getParentId();
        ProdCategory parent = getById(parentId);

        Long count;
        CriteriaQuery cq = new CriteriaQuery(ProdCategory.class);
        if (parentId.equals(0L)) {
            count = count(cq.eq("parentId", cs.getParams("parentId")));
            category.setCategoryLevel(1);
        } else {
            count = count(cq.eq("parentId", parent.getCategoryId()));
            Integer childLevel = FlymeUtils.getInteger(parent.getCategoryLevel(), 0) + 1;
            category.setCategoryLevel(childLevel);
        }
        Long sortOrder = FlymeUtils.getLong(count, 0L) + 1;
        category.setParentId(parentId);
        category.setCategoryName("分类名称" + sortOrder);
        category.setSortOrder(sortOrder.intValue());
        category.setCatagoryState(CommonConstants.ENABLED);
        category.setCompanyId(companyId);
        return ResultBody.ok();
    }

    @Override
    public ResultBody setState(Long categoryId, VisiableEnum visiableEnum) {
        ApiAssert.isNotEmpty("主键不能为空", categoryId);
        ApiAssert.isNotEmpty("状态不能为空", visiableEnum);
        UpdateWrapper up = new UpdateWrapper();
        up.set("catagoryState", visiableEnum.getCode());
        up.eq("categoryId", categoryId);
        boolean result = update(up);
        if (result) {
            return ResultBody.msg(visiableEnum.getName() + "成功");
        } else {
            return ResultBody.failed(visiableEnum.getName() + "失败");
        }
    }

    @Override
    @Transactional(propagation = Propagation.SUPPORTS, readOnly = true)
    public List<EntityMap> selectFirstCategory(String categoryName) {
        CriteriaQuery<EntityMap> cq = new CriteriaQuery(ProdCategory.class);
        cq.select(ProdCategory.class, "categoryId", "categoryName", "categoryIcon", "parentId");
        cq.eq("categoryLevel", CommonConstants.LEVEL_1);
        cq.likeRight("categoryName", categoryName);
        cq.orderByAsc("sortOrder");
        return selectEntityMap(cq);
    }

    @Override
    @Transactional(propagation = Propagation.SUPPORTS, readOnly = true)
    public List<EntityMap> selectSecondCategory(Long categoryId, String categoryName) {
        ApiAssert.isNotEmpty("请选择一级分类", categoryId);
        CriteriaQuery<EntityMap> cq = new CriteriaQuery(ProdCategory.class);
        cq.select(ProdCategory.class, "categoryId", "parentId", "categoryName", "categoryIcon");
        cq.eq("parentId", categoryId);
        cq.likeRight("categoryName", categoryName);
        cq.eq("categoryLevel", CommonConstants.LEVEL_2);
        cq.orderByAsc("sortOrder");
        return selectEntityMap(cq);
    }

    @Override
    @Transactional(propagation = Propagation.SUPPORTS, readOnly = true)
    public ResultBody selectAllCategory() {
        CriteriaQuery cq = new CriteriaQuery(ProdCategory.class);
        cq.select(ProdCategory.class, "categoryId", "parentId", "categoryLevel", "categoryName", "categoryIcon");
        cq.orderByAsc("sortOrder");
        List<EntityMap> allList = selectEntityMap(cq);
        List<EntityMap> result = buildTree(allList, 0L);
        return ResultBody.ok(result);
    }


    @Override
    @Transactional(propagation = Propagation.SUPPORTS, readOnly = true)
    public ResultBody selectShopCategory(Long shopId) {
        CriteriaQuery cq = new CriteriaQuery(ProdCategory.class);
        cq.select(ProdCategory.class, "categoryId", "parentId", "categoryLevel", "categoryName", "categoryIcon");
        cq.createJoin(ProdProduct.class).setMainField("categoryId").setJoinField("categoryId1");
        cq.eq(ProdProduct.class, "shopId", shopId);
        cq.orderByAsc("sortOrder");
        cq.groupBy("categoryId");
        List<EntityMap> categoryList1 = selectEntityMap(cq);

        CriteriaQuery cq2 = new CriteriaQuery(ProdCategory.class);
        cq2.select(ProdCategory.class, "categoryId", "parentId", "categoryLevel", "categoryName", "categoryIcon");
        cq2.createJoin(ProdProduct.class).setMainField("categoryId").setJoinField("categoryId2");
        cq2.eq(ProdProduct.class, "shopId", shopId);
        cq2.orderByAsc("sortOrder");
        cq2.groupBy("categoryId");
        List<EntityMap> categoryList2 = selectEntityMap(cq2);


        CriteriaQuery cq3 = new CriteriaQuery(ProdCategory.class);
        cq3.select(ProdCategory.class, "categoryId", "parentId", "categoryLevel", "categoryName", "categoryIcon");
        cq3.createJoin(ProdProduct.class).setMainField("categoryId").setJoinField("categoryId3");
        cq3.eq(ProdProduct.class, "shopId", shopId);
        cq3.orderByAsc("sortOrder");
        cq3.groupBy("categoryId");
        List<EntityMap> categoryList3 = selectEntityMap(cq3);

        List<EntityMap> allList = new ArrayList<>();
        if (FlymeUtils.isNotEmpty(categoryList1)) {
            allList.addAll(categoryList1);
        }
        if (FlymeUtils.isNotEmpty(categoryList2)) {
            allList.addAll(categoryList2);
        }
        if (FlymeUtils.isNotEmpty(categoryList3)) {
            allList.addAll(categoryList3);
        }
        List<EntityMap> result = buildTree(allList, 0L);
        return ResultBody.ok(result);
    }


    /**
     * 递归构建
     *
     * @param list
     * @param parentId
     * @return
     */
    private static List<EntityMap> buildTree(List<EntityMap> list, Long parentId) {
        List<EntityMap> result = new ArrayList();
        list.forEach(category -> {
            Long categoryId = category.getLong("categoryId");
            Long pid = category.getLong("parentId");
            Integer categoryLevel = category.get("categoryLevel");
            if (parentId.equals(pid)) {
                List child = buildTree(list, categoryId);
                if (categoryLevel.equals(1) || categoryLevel.equals(2)) {
                    category.put("child", child);
                }
                result.add(category);
            }
        });
        return result;
    }

    @Transactional(propagation = Propagation.SUPPORTS, readOnly = true)
    public ProdCategory getProdCategory(String categoryName, Long companyId) {
        CriteriaQuery<ProdCategory> cq = new CriteriaQuery(ProdCategory.class);
        cq.eq(true, "categoryName", categoryName);
        cq.eq(true, "companyId", companyId);
        return getOne(cq);
    }
}
